/**********************************************************************
 * File:        arab_classes.cpp
 * Description: This file groups all the classes inhereted from Tesseract's classes that
 *				need more attributes to be able to store Arabic text features and properties.
 * Author:      Fuad Jamour
 * Created:     Tue Mar 10 2009
 **********************************************************************/

#ifndef		ARAB_STRUCTS_H
#define		ARAB_STRUCTS_H

#include	"elst2.h"
#include	"points.h"
#include    "strngs.h"
#include	<string>

enum arabCharacters {UNKNOWN_CHAR,
					BAD_CHAR,
					SIN_B,
					SIN_M,
					SA7EN,
					ENDOFBA2,
					CURVE_E,
					PART_OF_CHAR,
					RAA2_E,
					PART_OF_MEEM,
					LOOP};


/**********************************************************************
 * PixelWithFeatures
 *
 * Used to store the coordinates, the feature code, and the angle of the feature.
 * The value of angle variable is assigned 10 for features that don't have an angle.
 * i.e. end points, branch points, and cross points don't have angles.
 **********************************************************************/
class PixelWithFeatures:public ELIST2_LINK {
public:
	PixelWithFeatures(){
		angle = 10;//10 is given to feature that has no angle(end, cross, and branch points
	}

	~PixelWithFeatures(){
	}


	PixelWithFeatures(ICOORD coords_v, BYTE feature_v) {
		coords = coords_v;
		feature = feature_v;
		angle = 10;
	}

	PixelWithFeatures(ICOORD coords_v, BYTE feature_v, double angle_v) {
		coords = coords_v;
		feature = feature_v;
		angle = angle_v;
	}

	void operator = (const PixelWithFeatures &other) {
		coords = other.coords;
		feature = other.feature;
		angle = other.angle;
	}

	ICOORD	coords;			//coordinates of the black pixel in the skeleton
	BYTE	feature;
	double	angle;
	NEWDELETE2 (PixelWithFeatures)
};
ELIST2IZEH (PixelWithFeatures)
/**********************************************************************
 * PixelWithDiffs
 *
 * Each pixel in a route of the thinned image has its coordinates, first difference, and second difference
 * stored for later work. a route is a stream of pixels connecting two features.
 **********************************************************************/
class PixelWithDiffs:public ELIST2_LINK {
public:
	PixelWithDiffs(){
	}

	~PixelWithDiffs(){
	}


	PixelWithDiffs(ICOORD coords_v) {
		coords = coords_v;
	}

//	void operator = (const PixelWithDiffs &other) {
//		coords = other.coords;
//		firstDiff = other.firstDiff;
//		scndDiff = other.scndDiff;
//	}


	ICOORD	coords;
	ICOORD	firstDiff;		//diff.x = x(current_pixel) - x(next_pixel)	|	diff.y = y(current_pixel) - y(next_pixel)
	ICOORD	scndDiff;		//scndDiff.x = diff.x(@current_pixel) - diff.x(@next_pixel)	|	scndDiff.y = diff.y(@current_pixel) - diff.y(@next_pixel)	
	NEWDELETE2 (PixelWithDiff)
};
ELIST2IZEH (PixelWithDiffs)
/**********************************************************************
 * Route
 *
 * The thinned image is divided into Routes, each route contains a list of PixelWithhDiffs list
 * and the details of the first and last pixels of the route.
 **********************************************************************/
class Route:public ELIST2_LINK {
public:
	Route(){
		isPartOfLoop = false;
		isInLoopDetection = false;
	}

	~Route(){
		coordsList.clear();
	}

	PixelWithDiffs_LIST* getPixelWithDiffsList() {
		return &coordsList;
	}

	void operator = (const Route &other) {//Fuad: revise, may cause runtime errors
		firstPt = other.firstPt;
		lastPt = other.lastPt;
		PixelWithDiffs_IT	source_it;
		source_it.set_to_list((PixelWithDiffs_LIST*)&(other.coordsList));
		PixelWithDiffs_IT	dest_it(&coordsList);
		coordsList.clear();
		for(source_it.move_to_first(), source_it.mark_cycle_pt(); !source_it.cycled_list(); source_it.forward()) {
			dest_it.add_after_stay_put(new PixelWithDiffs());
			*(dest_it.data()) = *(source_it.data());
		}
		//other.coordsList.deep_copy(&coordsList);
		isPartOfLoop = other.isPartOfLoop;
		isInLoopDetection = other.isInLoopDetection;
	}
	
	PixelWithFeatures	firstPt;
	PixelWithFeatures	lastPt;
	PixelWithDiffs_LIST	coordsList;
	bool				isPartOfLoop;			
	bool				isInLoopDetection;		//to be used temporarily while analyzing the loops
	NEWDELETE2 (Route)
};
ELIST2IZEH (Route)


/**********************************************************************
 * SEG_POINT
 *
 * The thinned image is divided into Routes, each route contains a list of PixelWithhDiffs list
 * and the details of the first and last pixels of the route.
 **********************************************************************/
class SEG_POINT:public ELIST2_LINK, public ICOORD {
public:
	SEG_POINT(){
		set_x(0);
		set_y(0);
		certainty = 0;
	}
	
	~SEG_POINT(){
	}

	SEG_POINT(ICOORD other){
		set_x(other.x());
		set_y(other.y());
		certainty = 0;
	}

	void operator = (const SEG_POINT &other) {
		set_x(other.x());
		set_y(other.y());
		certainty = other.certainty;
	}
	int		certainty;
	NEWDELETE2 (SEG_POINT)
};
ELIST2IZEH (SEG_POINT)

/**********************************************************************
 * PolygonalEdge
 *
 * To store the information of each edge in the polygonal approximation of the thinned image.
 **********************************************************************/
class PolygonalEdge:public ELIST2_LINK {
public:
	PolygonalEdge(){
	}

	~PolygonalEdge(){
	}

	PolygonalEdge(ICOORD coords_v, float angle_v) {
		coords = coords_v;
		angle = angle_v;
	}

	PolygonalEdge(ICOORD coords_v) {
		coords = coords_v;
	}

	void operator = (const PolygonalEdge &other) {
		coords = other.coords;
		angle = other.angle;
		bisectorAngle = other.bisectorAngle;
	}

	ICOORD	coords;
	float	angle;					//the angle of the edge is the smallest angle having the current edge as a center
	float	bisectorAngle;			//the angle besecting the angle of the edge, to be copied to the variable angle in PixelWithFeatures
									//to be used as the angle charecterizing the edge features
	NEWDELETE2 (PolygonalEdge)
};
ELIST2IZEH (PolygonalEdge)



//Fuad Sep 16, 2008
struct connCmpInf					
{
	int		x1 , x2 , y1 , y2 ;			//Integers to store coordinates of the connected component
	int		pixelsCnt;					//Number of pixels in the connected comonent
	int		area;
	double	density;
	bool	is_secondery;				//Bool to identify whether the component is a secondery or not
	BYTE	belongs_to	;				//If the component is secondery, belongs_to stores the code of 
									//the component the secondery belongs to
	int		groupSecondery;		    //n: if two seconderies belong to the same letter, then they will 
									//have the same groupSecondery value
	int		width;						//x2 - x1 + 1
	int		height;						//y2 - y1 + 1

	int		arabChar;

	PixelWithFeatures_LIST		featurePointsLst;
	Route_LIST					routeList;


	connCmpInf() {				//Default constructor
		x1 = 0;		x2 = 0;		y1 = 0;		y2 = 0;
		pixelsCnt = 0;
		area = 0;
		density = 0;
		is_secondery = false;
		belongs_to = 0;
		groupSecondery = 0;//n: 
		width = 0;
		height = 0;
		featurePointsLst.clear();
		routeList.clear();
		arabChar = 0;
	}

	~connCmpInf() {
		featurePointsLst.clear();
		routeList.clear();
	}

	void operator=(connCmpInf* right) {
		//right.featurePointsLst.deep_copy(&(this->featurePointsLst));
		//right.routeList.deep_copy(&(this->routeList));
		x1 = right->x1;
		x2 = right->x2;
		y1 = right->y1;
		y2 = right->y2;
		pixelsCnt = right->pixelsCnt;
		area = right->area;
		density = right->density;
		is_secondery = right->is_secondery;
		belongs_to = right->belongs_to;
		groupSecondery = right->groupSecondery;//n: 
		width = right->width;
		height = right->height;
		arabChar = right->arabChar;
	}

	
	void copy(connCmpInf* right) {
		//right.featurePointsLst.deep_copy(&(this->featurePointsLst));
		//right.routeList.deep_copy(&(this->routeList));
		x1 = right->x1;
		x2 = right->x2;
		y1 = right->y1;
		y2 = right->y2;
		pixelsCnt = right->pixelsCnt;
		area = right->area;
		density = right->density;
		is_secondery = right->is_secondery;
		belongs_to = right->belongs_to;
		groupSecondery = right->groupSecondery;//n: 
		width = right->width;
		height = right->height;
		arabChar = right->arabChar;
	}


};

struct subword						
{
	int x1 , x2 , y1 , y2 ;			//Integers to store coordinates of the subword
	BYTE color;						//To hold the color of the subword's main component

	std::string	arabCharFromTru;

	subword()					//Default constructor
	{
		x1 = 0;		x2 = 0;		y1 = 0;		y2 = 0;
		color = 0;
		arabCharFromTru.clear();
	}

	void operator= (subword* right) {
		x1 = right->x1;
		x2 = right->x2;
		y1 = right->y1;
		y2 = right->y2;
		color = right->color;
	}
};

#endif